import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';

class DioUtils {
  static final DioUtils _singleton = DioUtils._init();
  static Dio _dio;

  ///是否是debug模式
  static bool _isDebug = false;

  ///打开debug模式
  static void openDebug() {
    _isDebug = true;
  }

  DioUtils._init() {
    BaseOptions options =
        BaseOptions(connectTimeout: 1000 * 10, receiveTimeout: 1000 * 20);
    _dio = Dio(options);
  }

  factory DioUtils() {
    return _singleton;
  }

  ///http request with options
  /// [method] The request method.
  /// [path] The url path.
  /// [data] The request data.
  /// [options] The request options.
  /// String 返回 json data.
  Future<Map> request<T>(String path,
      {String method = Method.get,
      queryParameters,
      Options options,
      CancelToken cancelToken}) async {
    Response response = await _dio.request(path,
        queryParameters: queryParameters,
        options: _checkOptions(method, options),
        cancelToken: cancelToken);
    if (response.statusCode == 200) {
      try {
        if (response.data is Map) {
          if (response.data['ok'] != null &&
              !response.data['ok'] &&
              response.data['msg'] != null &&
              response.data['code'] != null) {
            return Future.error(DioError(
                response: response,
                message: response.data['msg'],
                type: DioErrorType.RESPONSE));
          }
          //由于小说接口返回的格式不固定不规范，所以直接返回，这里一般返回BaseResp
          return response.data;
        } else {
          if (response.data is List) {
            Map<String, dynamic> _dataMap = {};
            _dataMap['data'] = response.data;
            return _dataMap;
          }
        }
      } catch (e) {
        return Future.error(DioError(
            response: response,
            message: "data parsing exception...",
            type: DioErrorType.RESPONSE));
      }
    }
    return Future.error(DioError(
        response: response,
        message: "statusCode: ${response.statusCode}, service error",
        type: DioErrorType.RESPONSE));
  }

  Options _checkOptions(method, options) {
    options ??= Options();
    options.method = method;
    return options;
  }

  void _printHttpLog(Response response) {
    if (!_isDebug) {
      return;
    }
    try {
      _printDataStr("request_data", response.request.data);
      _printDataStr("query_parameters", response.request.queryParameters);
      _printDataStr("response", response.data);
    } catch (ex) {
      if (kDebugMode) {
        print("Http Log error.......");
      }
    }
  }

  String _getOptionsStr(RequestOptions request) {
    return "method:" +
        request.method +
        " baseUrl:" +
        request.baseUrl +
        " path:" +
        request.path;
  }

  void _printDataStr(String tag, Object value) {
    String da = value.toString();
    while (da.isNotEmpty) {
      if (da.length > 512) {
        da = da.substring(512, da.length);
      } else {
        da = "";
      }
    }
  }
}

///<BaseRespR<T> 返回 status code msg data Response.
class BaseRespR<T> {
  String status;
  int code;
  String msg;
  T data;
  Response response;

  BaseRespR(this.status, this.code, this.msg, this.data, this.response);

  @override
  String toString() {
    StringBuffer sb = StringBuffer('{');
    sb.write("\"status\":\"$status\"");
    sb.write(",\"code\":$code");
    sb.write(",\"msg\":\"$msg\"");
    sb.write(",\"data\":\"$data\"");
    sb.write('}');
    return sb.toString();
  }
}

/// 请求方法.
class Method {
  static const String get = "GET";
  static const String post = "POST";
  static const String put = "PUT";
  static const String head = "HEAD";
  static const String delete = "DELETE";
  static const String patch = "PATCH";
}
